home *** CD-ROM | disk | FTP | other *** search
- printer.device V44 (OS 3.5)
-
- Drivers for the new printer.device.
-
- The new printer.device offers many new possibilities for printer
- drivers and does away with some problems of the old printer.device.
-
- Changes:
-
- 1. The driver now always runs in a DOS process with a minimum stack
- size of 8 KB.
-
- 2. The PWrite and PBothReady functions can now sensibly used in
- every situation, even during DoSpecial.
-
- 3. Due to an extension of the command table, accidental exchanges of
- PWrite output from DoSepcial and printer.device output can be avoided.
-
- 4. Drivers can return error messages from all necessary situations
- (including DoSpecial) and can use error codes of their own.
-
- 5. Drivers are resposible for formatting and localizing their error codes.
-
- 5. Drivers can perform color conversion, color correction, dithering etc.
- by themselves without having to fear side-effects with the printer.device
- or having to use the incovenient PDERR_TOOKCONTROL.
-
- 6. Scaling can be done entirely by printer.device but it is also possible
- to request that no scaling be performed at all.
-
- 7. Drivers can use their own structure for color. This enables the use of
- standard implementations for color space conversion etc.
-
- 8. Drivers can use the new PRead function to read from the I/O interface.
-
- 9. Drivers can influence the display of the printer preferences in order
- to adapt them to their interpretation of the settings.
-
- 10. Drivers can manage their settings themselves and are allowed to have
- a printer dialog of their own.
-
- 11. Drivers can return new information to applications in order to improve
- the printing result.
-
-
- Converting an old driver into a new driver
-
- 1. Set driver identification
-
- A new driver must have a version number of 44 or better and must have the
- PPCF_EXTENDED bit set in ped_PrinterClass. After that the PrinterExtendedData
- structure must be extended with the following fields:
-
- ped_TagList is a pointer to a tag list that contains for the most part
- the extended driver definition.
-
- ped_DoPreferences is a function pointer. The funtion is called in order to
- manage the different commands for the driver-specific settings.
-
- ped_CallErrHook is a function pointer. The function is called in order to
- format driver-specific error codes and output it through a hook.
-
- The tags of ped_TagList in full:
-
- PRTA_8BitGuns: If the value of this tag is TRUE, every color will be computed
- using 256 intensities. This makes up to 16 million colors possible (although
- hardly any printer can print all of them). If this tag is not present or
- FALSE, 16 intensities per color are used, just like in previous versions
- of AmigaOS. New drivers should set this tag under any circumstances.
-
- PRTA_ConvertSource: If the value of this tag is TRUE, printer.device
- will leave the conversion from the sRGB color space into the printer-specific
- color space (often YMCK) to the driver. The conversion will then be
- performed by calling the ped_Render function with a status of 8.
- The first parameter is a pointer to 24 bit BGR values (please note the
- unuals BGR order which is used for compatibility reasons) the
- second parameter contains the number of pixels in the array and the
- third parameter is 0 if the array is a colormap or 1 if the the array
- is a pixel lin. The size of each entry is given either by PRTA_ColorSize
- or by sizeof(union colorEntry).
-
- PRTA_FloydDithering: If the value of this tag is TRUE, the printer.device
- will leave the floyd-steinberg dithering (or whatever dithering is used)
- to the driver. If the PRTA_8BitGuns tag is TRUE, this tag is set to TRUE
- implicitly, i.e. normally the driver itself is responsible for the third
- dither method as well.
-
- PRTA_AntiAlias: If the value of this tag is TRUE, the printer.device will
- leave the smoothing to the driver. In this case the driver must perform
- the smoothing in the render 1 call.
-
- PRTA_ColorCorrection: If the value of this tag is TRUE, the printer.device
- will leave any color correction to the driver. Due to the rudimentary nature
- of the built-in color correction of the printer.device it is highly reccommended
- to perform the color correction inside the driver - the color correction
- of printer.device will almost never fulfill the needs of modern printers.
- The color correction is performed by calling the ped_Render function
- with a status of 9. The first parameter is a pointer to a color array,
- the second parameter specifies the number of elements in the array and
- the third parameter is 0 for a color map or 1 for a pixel line.
-
- PRTA_NoIO: If the value of this tag is TRUE, no I/O device will be opened.
- In this case the driver must not call PWrite, PBothRead or PRead. Any ouput
- must be performed directly by the driver. In this way fax drivers or drivers
- that place their ouput in a file will no longer unecessarily allocate I/O resources.
-
- PRTA_NewColor: If the value of this tag is TRUE, printer.device will not care
- for the colors after conversion anymore. This tag implies that the tags
- PRTA_ConvertSource, PRTA_FloydDithering, PRTA_AntiAlias and
- PRTA_ColorCorrection all have a value of true.
-
- PRTA_ColorSize: The value of this tag defines the size of a color or a pixel.
- The standard value is sizeof(union ColorEntry). With the help of this tag
- the driver can save more information inside a color and support more
- complex color spaces. If the driver doesn't have the PRTA_NewColor tag set
- and uses one of the printer.device algorithms for conversion, correction or
- anti-alias, every pixel will be interpreted as a ColorEntry union, even
- if a larger value is used as the total size of a pixel. Therefore in most
- cases it will be necessary to combine a color structure that is not identical
- to union ColorEntry with the PRTA_NewColor tag.
-
- PRTA_NoScaling: If a driver wants to inhibit any scaling of the raw data
- by printer.device, it can do so by use of this tag. However, the scaling
- will still be computed, i.e. the number printer columns and lines in
- render case 1 will still be equal to the scaled values. The size of the
- raw data can be obtained from the PrtInfo.pi_width and pi_height fields.
- This tag automatically implies TRUE values for PRTA_FloydDithering and
- PRTA_AntiAlias since these algorithms can only operate on scaled data.
-
- PRTA_DitherNames: The value of this tag is an array of 3 strings - names
- for the dithering methods PD_ORDERED, PD_HALFTONE and PD_FLOYD. If a
- driver uses dithering methods different from those it should use the tag
- in order to appropriately name the dither methods.
-
- PRTA_ShadingNames: The value of this tag is an array of 4 strings - names
- for the shading types PS_BW, PS_GREYSCALE, PS_COLOR and PS_GREY_SCALE2.
- The last two strings are exchanged in their order compared to the order
- used in the printer preferences! If a driver uses shading methods different
- from the default (e.g. a special variant of grey values in the case of PS_COLOR
- for black/white printers), it should use the tag to appropriately name
- the shading methods. Please note that the PS_GREY_SCALE2 method is used
- internally by printer.device as a special case for the A2024 grey scale
- monitor, so that replacing this method does not make much sense.
-
- PRTA_ColorCorrect: If a driver can not understand the separate setting of
- color correction for the red, green and blue color channels, it should set
- this tag to FALSE so that the checkmarks become disabled in the preferences.
-
- PRTA_DensityInfo: Drivers that use the density settings to make further
- changes to the output (e.g. amount of ink) can use this tag to provide
- user information for every density. The value of this tag is an array of
- 8 string. The first string is currently ignored and must be NULL while
- the other 7 strings correspond to the densities 1 to 7 and are displayed
- accordingly by the printer preferences.
-
- PRTA_LeftBorder, PRTA_TopBorder: Most printers have small paper margins.
- The left and top border on the paper onto which the printer can not print
- is specified in inches/1000 using these tags. The right and bottom margins
- are set according to the printable area. Applications can use the information
- on the margins and printable area to accurately place the printer output
- on the paper.
-
- PRTA_MixBWColor: If an application uses segemented (striped) printing it
- can often significantly improve the printing speed if it prints segments
- that contain only black graphics/text using the black/white mode of the
- printer; segments with color graphics will be printed using the greyscale
- or color mode accordingly. However, some printers use a different ink
- cartrige for black/white printing than they use for color printing or
- they use black ink in black/white mode and mix black from yellow,
- cyan and magenta while in color mode. In both cases an optimization by
- the application is undesirable. If the value of this tag is FALSE,
- applications should refrain from performing such optimizations.
-
- PRTA_Preferences: If the driver uses a driver-specific set of options and
- if these options options can be changed via the driver, this tag displays
- these circumstances with a value of TRUE. Applications will then allow
- access to a button labelled "Options..." which allows the user to open
- a window for editing the driver options. This is achieved by using the
- new command PRD_EDITPREFS.
-
-
- 2. Adapt algorithms
-
- The transfer function
-
- The Transfer() function of the driver that is responsible to transfer the
- pixels into the printer buffer does not need to perform scaling anymore.
- Up to know the special case of X-stretching was left to the drivers. This
- is now handled by the printer.device in all cases, the pi_ScaleX field only
- contains ones so the the loop for using a specific X-value an corresponding
- amount of times can be removed from the function.
-
- New drivers should set the PRTA_8BitGuns tag and support printing with 256
- intesities per color channel. Normally this shouldn't involve much work as
- the typical transfer function will work just the same with 8 bits as it
- does with 4.
-
- Two points have to be taken into account, though: The threshold value
- pi_Threshold has already been stretched to 256 intensities. Many drivers
- invert this value before using it, so care must be taken to perform the
- inversion in the correct range of values.
-
- The dither matrices pi_dmatrix still correspond to the dither methods ordered
- and halftone with a grid size of 4x4. Using these matrices results in a
- maximum of 16 intensities per color channel in the final printout and thus
- results in very marginal improvements when compared to the old drivers.
- Instead you should use differently sized matrices depending on the print
- resolution, e.g. 8x8. In the case of the Floyd-Steinberg dithering algorithm
- the pi_dmatrix matrix will contain only averag intensities and is not
- suitable for dithering.
-
- Density calculation
-
- The SetDensity function must adjust the values of the PRTA_Leftborder,
- PRTA_TopBorder and PRTA_MixBWColor if these depend on the printing resolution.
- However, this will not apply to most printers. Applications, on the other hand,
- are encouraged to re-read theses values for every print density.
-
- The render function
-
- Two cases for the render function have been added:
-
- Case 8: The function is called with status 8 if colors have to converted from
- RGB to the format of the driver. The first parameter ct contains a pointer to
- an array of color. Every entry has a size corresponding to the PRTA_ColorSize
- tag or sizeof(union ColorEntry).
- If you interpret the entries as a union ColorEntry the bytes with the indices
- PCMRED, PCMGREEN, PCMBLUE will receive the RGB values. The x parameter holds
- the number of entries in the array. The y parameter contains a 0 for a colormap
- and a 1 for a line of pixels.
-
- The standard conversion from RGB data to YMCK (as it is used in printer.device)
- can look like this:
-
- case 8: /* Convert RGB source to union ColorEntry */
- {
- /*
- ct - union colorEntry *, pointer to RGB data
- x - width, number of colors in ct array
- y - 0: converting colormap, 1: converting pixel row
- */
- union colorEntry *ColorInt = (union colorEntry *) ct;
- LONG width = x;
- ULONG additive = 0xffffffff;
- additive ^= (PD->pd_Preferences.PrintImage == IMAGE_NEGATIVE) ? 0xffffffff : 0;
- if (PD->pd_Preferences.PrintShade == SHADE_COLOR)
- {
- /* we don't need PCMBLACK, so don't calculate it */
- do
- {
- ColorInt->colorLong ^= additive;
- ColorInt++;
- }
- while (--width);
- }
- else
- {
- /* calculate PCMBLACK */
- do
- {
- ColorInt->colorLong ^= additive;
- ColorInt->colorByte[PCMBLACK] =
- (ColorInt->colorByte[PCMYELLOW]
- + ColorInt->colorByte[PCMMAGENTA]
- + ColorInt->colorByte[PCMCYAN]) / 3;
- ColorInt++;
- }
- while (--width);
- }
- break;
- }
-
- Especially the calculation of the grey scale value can differ from the simple
- arithmetic average of the three color intensities.
-
-
- Case 9: The function is called with status 9 if colors are to be corrected.
- The first parameter ct contains a pointer to an array of colors in the format
- of the driver (after render call 8). Every entry has the size specified by
- the PRTA_ColorSize tag or sizeof(union ColorEntry).
- The x parameter contains the number of entries in the array. The y parameter
- is 0 for a color map and 1 for a line of pixels.
-
- The DoSpecial function
-
- If an entry in the command table "CommmandTable" contains "\377", the
- DoSpecial() function will be called. What's new: if a command contains
- the string "\377\377" the I/O buffers will be flushed prior to calling the
- function. This enables the driver to perform I/O on its own by calling PWrite,
- PBothReady and PRead, without any danger of the I/O becoming mixed up.
-
- The result of the function is interpreted differently in order to enable
- DoSpecial to return general printer errors:
-
- Value Interpretation
- >0 Number of characters in the buffer
- 0 Command not handled by DoSpecial
- -1 Unsupported command
- -2 (new) Command was executed but no characters were written
- to the buffer
- <-2 (new) An I/O or printer error minus 65536.
-
- In order to return an error from DoSpecial you simply have to subtract
- 65536 from the actual error code.
-
-
- 3. Error handling
-
- The new ped_CallErrHook field of the PrinterExtendedData structure contains
- a function which is called if an error code of the driver needs to formatted
- for output via a hook.
-
- The driver can define error codes between PDERR_FIRSTCUSTOM and PDERR_LASTCUSTOM
- and return them from its functions. If the application has set a hook to output
- an error directly through the printer.device, the ped_CallErrHook function will
- be called for all error codes of the driver.
-
- The first parameter of the function is a pointer to the I/O request that receives
- the error in io_Error. The second parameter is the hook that was set by the
- applicatioin. The driver must fill in a variable of PrtErrMsg type and then
- call the pd_CallErrHook function of the PrinterData structure. This will in
- turn contain the hook as the first parameter, the I/O request as the second
- parameter and a pointer to a variable of PrtErrMsg type as the third parameter.
- des Typs PrtErrMsg.
-
- void ErrHook(struct IORequest *ior, struct Hook *hook)
- {
- struct EasyStruct es;
- struct PrtErrMsg pem;
- LONG args[2];
- es.es_StructSize = sizeof(es);
- es.es_Flags = 0;
- es.es_Title = NULL;
- es.es_GadgetFormat = "OK";
- pem.pe_Version = PDHOOK_VERSION;
- pem.pe_ErrorLevel = RETURN_FAIL;
- pem.pe_Window = NULL;
- pem.pe_ES = &es;
- pem.pe_IDCMP = NULL;
- pem.pe_ArgList = NULL;
- switch (ior->io_Error)
- {
- case FILEERR_FILEOPENFAILED:
- es.es_TextFormat = "Unable to open file %s.";
- args[0] = (LONG) outfile;
- pem.pe_ArgList = args;
- break;
- }
- PD->pd_CallErrHook(hook,ior,&pem);
- }
-
- The es.es_Title and es.es_GadgetFormat fields may be NULL, the pd_CallErrHook
- will fill them appropriately before calling the hook.
-
-
- 4. Driver settings
-
- If the driver support proprietary (driver-specific) settings it must set
- the PRTA_Preferences to TRUE and enter a function into ped_DoPreferences
- that handles the settings.
-
- Drivers can support different concepts for settings. If the driver is likely
- to be used by several units it should save a separate pareferences file
- for each unit. If it is likely to be used by only one unit it is sufficient
- to use one preferences file. If the driver derives the name of the settings
- file from the driver name, the user will still be able to manage several
- sets of preferences by duplicating the driver and giving it a new name.
-
- Another decision has to be made with regard to the size of the preferences
- dialog. If the driver supports a very large amount of settings it often
- makes sense for the driver to provide a separate preferences editor (e.g.
- PrinterPS) that can be used to control all settings. In this case the dialog
- that is opened by the PRD_EDITPREFS command should only contain that part
- of the settings that directly affects the printer output.
-
- The ped_DoPreferences function is called using 2 parameters: one I/O request
- and one command. The command can state 7 different cases:
-
- Case 0: set the preferences to their default values (PRD_RESETPRFS)
-
- Case 1: load the preferences from a file (PRD_LOADPREFS)
-
- Case 2: store the preferences in a file in ENV: (PRD_USEPREFS)
-
- Case 3: store the preferences in a file both in ENV: and in ENVARC:
- (PRD_SAVEPREFS)
-
- Case 4: store the preferences into an I/O buffer (PRD_READPREFS)
-
- Case 5: copy the preferences from an I/O buffer (PRD_WRITEPREFS)
-
- Case 6: open a window in which the preferences can be changed
- (PRD_EDITPREFS)
-
-
- Details of the preferences structure
-
- A structure that is used for saving the preferences must be derived from
- the PrtDriverPreferences structure (Include devices/prtbase.h):
-
- struct PrtDriverPreferences
- {
- UWORD pdp_Version; /* PRIVATE! driver specific version */
- UBYTE pdp_PrinterID[32]; /* PRIVATE! driver specific id */
- char pdp_PrefName[FILENAME_SIZE-16];
- ULONG pdp_Length; /* length of this structure */
- /* more driver private fields follow*/
- };
-
- By reading the version and printerID the driver can tell its settings from
- that of other drivers and can recognize older settings.
-
- The PrefName array should contain a readable name for the preferences, this
- could e.g. be the name of the printer.
-
- Default values
-
- In the beginning many programs will not offer the possibility to open the
- preferences dialog (case 6). Therefore it is vital that the default values
- actually make sense and are usable.
-
- Loading and saving of preferences
-
- The settings of a driver will automatically be loaded when opening a unit.
- The file format should be an IFF FORM PREF and be structured the same way
- the system files are (i.e. it should contain a FORM PRHD and a separate FORM
- for the actual settings).
-
- Reading and writing of preferences
-
- An application may read the settings of the driver and store it for later
- reference (e.g. to save it while the unit is closed). Likewise it may
- write back the settings to the driver.
-
- case 4:
- /* copy preferences to ior */
- sior = (struct IOStdReq *) ior;
- if (sior->io_Data && sior->io_Offset == 0 && sior->io_Length >= sizeof(DriverPrefs))
- {
- CopyMem(&DriverPrefs,sior->io_Data,sizeof(DriverPrefs));
- sior->io_Actual = sizeof(DriverPrefs);
- }
- else
- error = IOERR_BADLENGTH;
- break;
- case 5:
- /* check prefs in ior and copy it to preferences */
- sior = (struct IOStdReq *) ior;
- if (sior->io_Data && sior->io_Offset == 0 && sior->io_Length >= sizeof(struct PrtDriverPreferences))
- {
- tp = (struct FileDriverPrefs *) sior->io_Data;
- /* check prefs data. If this check fails 0 is returned but
- io_Actual is set to 0.
- */
- if (checkDriverPrefs(&tp->fdp_Base))
- {
- CopyMem(tp,&DriverPrefs,sizeof(DriverPrefs));
- sior->io_Actual = sizeof(DriverPrefs);
- }
- else
- sior->io_Actual = 0;
- }
- else
- error = IOERR_BADLENGTH;
- break;
-
- Damit der Treiber seine Einstellungen wiedererkennt, muß er den Kopf der
- Datenstruktur überprüfen:
-
- static int
- checkDriverPrefs(struct PrtDriverPreferences *p)
- {
- if (p->pdp_Version == 1
- && strcmp(p->pdp_PrinterID,DriverPrefsDefault.fdp_Base.pdp_PrinterID) == 0
- && p->pdp_Length == sizeof(struct FileDriverPrefs))
- {
- return TRUE;
- }
- return FALSE;
- }
-
- Please note that in the case of an unrecognized structure no error will
- be returned but only io_Actual is set to 0. This means that the application
- can write back settings that were stored earlier (even in a file) - this
- makes a change or update of the driver "in between" possible.
-
- Edit preferences
-
- The I/O request for editing preferences (struct IOPrtPrefsReq) contains
- a tag list:
-
- PPRA_Window: The value of this tag denotes a window. This window determines
- the screen to use for the preferences dialog. The window should be locked
- against input as long as the dialog remains opened.
-
- PPRA_Screen: If now window was specified this tag can be used to specify
- a screen on which to open the preferences dialog.
-
- PPRA_PubScreen: The name of a public screen on which to open the
- preferences dialog.
-
- The only ways to leave the preferences dialog should be by way of an "OK"
- and a "Cancel" button, i.e. the settings will not be saved from within
- the dialog. The saving of the settings must be handled either by the
- application through PRD_READPREFS/PRD_WRITEPREFS, by a separate preferences
- editor or by a system application using PRD_SAVEPREFS.
-
-
- 5. Driver-specific color structure
-
- A driver can define a color structure best suited to its needs, i.e. it
- need not use the standard union colorEntry structure. All printer.device
- needs to know is the size of the structure which is achieved by use of
- the PRTA_ColorSize tag. This of course means that the printer.device can
- only provide a very limited amount of services to the driver:
- Reading the bitmap and converting the data to 24 bit RGB and scaling the
- RGB data. All other tasks (converting from sRGB color space to the printer
- color space, color correction, dithering, anti-alias) must be performed
- by the driver.
-
- If the driver uses a color structure that is different from union colorEntry
- it must set the PRTA_NewColor tag. The printer.device will then implicitly
- set all tags that affect the printing algorithms.
-
- If the driver only requires some addtionals bytes in the color structure,
- e.g. for temporary data while dithering, it can use PRTA_ColorSize to
- set the size of the new color structure but leave PRTA_NewColor set to
- FALSE. Please note that in this case the color structure must begin with
- union colorEntry because this is the way the printer.device interprets
- the structure:
-
- struct LargeColorEntry
- {
- union colorEntry lce_ColorEntry;
- LONG lce_Random;
- };
-